package com.ux.widget;

import java.util.ArrayList;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import com.learn.animation.R;
import com.ux.widget.helper.ResideMenuDragHelper;
import com.ux.widget.helper.ResideMenuDragHelper.DragDirection;
import com.ux.widget.helper.ViewUtils;

public class ResideMenuView extends FrameLayout implements View.OnClickListener {
	
	private final boolean DEBUG_VIEW = false;
	
	FrameLayout uxResideLeftView;
	FrameLayout uxResideRightView;
	FrameLayout uxResideMainViewRoot;
	View uxResideMainViewDragZoneDetectorLeft, uxResideMainViewDragZoneDetectorRight;
	FrameLayout uxResideMainView;
	FrameLayout uxResideSlideUpViewRoot;
	FrameLayout uxResideCrotonToastView;
	LinearLayout uxResideMenuView;
	
	ViewGroup mRootView;
	
	int mScreenWidth, mScreenHeight;
	
	ResideMenuDragHelper mResideMenuDragHelper;
	
	public ResideMenuView(Context context) {
        super(context);
        init(context);
	}
	
	public ResideMenuView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public ResideMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context);
	}
	
	public interface Callback {
		/**
         * the method will call on the finished time of opening menu's animation.
         */
		public void onMenuOpened(DragDirection direction);
		
		//public void onMenuOpenning(DragDirection direction);
		
		/**
         * the method will call on the finished time of closing menu's animation  .
         */
		public void onMenuClosed();
	}
	
	private void init(Context context){
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.ux_reside_layout, this);
        
        uxResideLeftView = (FrameLayout) findViewById(R.id.uxResideLeftView);
    	uxResideRightView = (FrameLayout) findViewById(R.id.uxResideRightView);
    	
    	uxResideMainViewRoot = (FrameLayout) findViewById(R.id.uxResideMainViewRoot);
    	uxResideMainView = (FrameLayout) findViewById(R.id.uxResideMainView);
    	uxResideMainViewDragZoneDetectorLeft = findViewById(R.id.uxResideMainViewDragZoneDetectorLeft);
    	uxResideMainViewDragZoneDetectorRight = findViewById(R.id.uxResideMainViewDragZoneDetectorRight);
    	
    	uxResideSlideUpViewRoot = (FrameLayout) findViewById(R.id.uxResideSlideUpViewRoot);
    	uxResideCrotonToastView = (FrameLayout) findViewById(R.id.uxResideCrotonToastView);
    	uxResideMenuView = (LinearLayout) findViewById(R.id.uxResideMenuView);
    	
    	// TODO init for DragHelper
    	mRootView = (ViewGroup) findViewById(R.id.uxResideRootView);
    	mResideMenuDragHelper = ResideMenuDragHelper.create(mRootView, null);
    	_registerDragEvent();
    	
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        mScreenWidth = metrics.widthPixels;
        mScreenHeight = metrics.heightPixels;
    	
    	int dragZoneDetectorWidth = mResideMenuDragHelper.getDragZoneDetectorWidth();
    	
    	if (DEBUG_VIEW) {
	    	int debugViewBgColor = Color.parseColor("#55000000");
	    	uxResideMainViewDragZoneDetectorLeft.setBackgroundColor(debugViewBgColor);
	    	uxResideMainViewDragZoneDetectorRight.setBackgroundColor(debugViewBgColor);
    	}
    	
    	uxResideMainViewDragZoneDetectorLeft.getLayoutParams().width = dragZoneDetectorWidth;
    	uxResideMainViewDragZoneDetectorRight.getLayoutParams().width = dragZoneDetectorWidth;
    	
    	// some hack to get real size of our View
    	final ViewTreeObserver vto = this.getViewTreeObserver();
		vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
			@SuppressWarnings("deprecation")
			public void onGlobalLayout() {
				// update main view and bottom menu view
				Log.d("mapp", "[INF] onGlobalLayout <<<");
				uxResideMainView.setPadding(0, 0, 0, uxResideMenuView.getHeight());
				uxResideSlideUpViewRoot.setPadding(0, 0, 0, uxResideMenuView.getHeight());
				if (vto.isAlive()) {
					if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
						vto.removeGlobalOnLayoutListener(this);						
					} else {
						vto.removeOnGlobalLayoutListener(this);						
					}
				}
			}
		});
    }
	
	public void registerCallbackEvent(Callback callback) {
		mResideMenuDragHelper.registerCallbackEvent(callback);
	}
	
	private void _registerDragEvent() {
		uxResideMainViewDragZoneDetectorLeft.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				mResideMenuDragHelper.processTouchEvent(event, DragDirection.DRAG_DIRECTION_FROM_LEFT);
				return true;
			}
		});
		uxResideMainViewDragZoneDetectorRight.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				mResideMenuDragHelper.processTouchEvent(event, DragDirection.DRAG_DIRECTION_FROM_RIGHT);
				return true;
			}
		});
	}
	
	@Override
	public void onClick(View v) {
		// in case BottomMenuItemView clicked
		if (v.getTag() != null && menuItemViewListener != null) {
			try {
				menuItemViewListener.onMenuItemClicked(_menuItemList.get((Integer) v.getTag()));
			} catch (IndexOutOfBoundsException ex) {
				ex.printStackTrace();
			}
		}
	}

	private BottomMenuItemViewListener menuItemViewListener;
	private ArrayList<BottomMenuItemView> _menuItemList = new ArrayList<BottomMenuItemView>();
	
	private boolean isSlideUpPanelShowed = false;
	
	// TODO public method - START
	/**
	 * show full SlideUpView (overlap ActionBar)
	 * @param show
	 */
	public void openSlideUpView(boolean show) {
		openSlideUpView(show, true);
	}
	public void openSlideUpView(boolean show, boolean overlapActionBar) {
		int pivotY = mScreenHeight - uxResideMenuView.getHeight();
		if (show) {
			isSlideUpPanelShowed = true;
			uxResideSlideUpViewRoot.setY(pivotY);
			uxResideSlideUpViewRoot.setAlpha(0.0f);
			uxResideSlideUpViewRoot.setVisibility(View.VISIBLE);
			
			uxResideSlideUpViewRoot.requestFocus();
			
			//uxResideSlideUpViewRoot
			AnimatorSet slideUpAnimatorSet = new AnimatorSet();
	    	
    		slideUpAnimatorSet.playTogether(
    				ObjectAnimator.ofFloat(uxResideSlideUpViewRoot, "translationY", overlapActionBar ? 0 : ViewUtils.dpToPx(getContext(), 48)),
    				ObjectAnimator.ofFloat(uxResideSlideUpViewRoot, "alpha", 1.0f)
    				);
	    	
	    	slideUpAnimatorSet.setDuration(500);
	    	
	    	slideUpAnimatorSet.start();
		} else { // hide
			if (!isSlideUpPanelShowed) {
				// not action when it already hide 
				return;
			}
			AnimatorSet slideDownAnimatorSet = new AnimatorSet();
	    	
    		slideDownAnimatorSet.playTogether(
    				ObjectAnimator.ofFloat(uxResideSlideUpViewRoot, "translationY", pivotY),
    				ObjectAnimator.ofFloat(uxResideSlideUpViewRoot, "alpha", 0.0f)
    				);
    		slideDownAnimatorSet.addListener(new AnimatorListener() {
				
				@Override
				public void onAnimationStart(Animator animation) {
					// not handle
				}
				
				@Override
				public void onAnimationRepeat(Animator animation) {
					// not handle
				}
				
				@Override
				public void onAnimationEnd(Animator animation) {
					uxResideSlideUpViewRoot.setVisibility(View.GONE);
					isSlideUpPanelShowed = false;
				}
				
				@Override
				public void onAnimationCancel(Animator animation) {
					// not handle
				}
			});
    		
	    	slideDownAnimatorSet.setDuration(400);
	    	
	    	slideDownAnimatorSet.start();
		}
	}
	public interface BottomMenuItemViewListener {
		public void onMenuItemClicked(BottomMenuItemView menuItem);
	}
	public void addBottomMenuItemViewListener(BottomMenuItemViewListener listener) {
		menuItemViewListener = listener;
	}
	public void addBottomMenuItem(BottomMenuItemView menuItem) {
		if (menuItem == null) {
			return;
		}
		if (_menuItemList.size() >= 4) {
			Log.e("mapp", "[ERR] cannot add more than 4 menu item");
			return;
		}
		_menuItemList.add(menuItem);
		
		// register click event
		View menuIconView = menuItem.getIconView();
		menuIconView.setTag(menuItem.getId());
		menuIconView.setOnClickListener(this);
		
		ViewGroup menuView = menuItem.getView();
		uxResideMenuView.addView(menuView);
	}
	public void addViewToTop(ViewGroup view) {
		if (view == null) {
			return;
		}
		mRootView.addView(view);
	}
	public void setMainViewBackgroundResource(int resid) {
		uxResideMainViewRoot.setBackgroundResource(resid);
	}
	public void updateMainView(FragmentManager fm, Fragment fragment) {
		_setFragment(fm, R.id.uxResideMainView, fragment);
	}
	public void updateSlideUpView(FragmentManager fm, Fragment fragment) {
		_setFragment(fm, R.id.uxResideSlideUpViewContent, fragment);
	}
	public ViewGroup getMainView() {
		return (ViewGroup) findViewById(R.id.uxResideMainView);
	}
	
	public void updateRightMenuContent(FragmentManager fm, Fragment fragment) {
		_setFragment(fm, R.id.uxResideRightView, fragment);
		mResideMenuDragHelper.updateRightMenuContentWidth();
	}
	
	public void updateLeftMenuContent(FragmentManager fm, Fragment fragment) {
		_setFragment(fm, R.id.uxResideLeftView, fragment);
		mResideMenuDragHelper.updateLeftMenuContentWidth();
	}
	
	public void openMenu(DragDirection direction) {
		mResideMenuDragHelper.openMenu(direction);
	}
	
	public void closeOpenedResideMenu() {
		mResideMenuDragHelper.closeOpenedResideMenu();
	}
	
	public void setDisableDrirection(DragDirection direction, boolean enable) {
		if (direction == DragDirection.DRAG_DIRECTION_FROM_LEFT) {
			uxResideMainViewDragZoneDetectorLeft.setVisibility(enable ? View.VISIBLE : View.GONE);
		} else if (direction == DragDirection.DRAG_DIRECTION_FROM_RIGHT) {
			uxResideMainViewDragZoneDetectorRight.setVisibility(enable ? View.VISIBLE : View.GONE);
		}
	}
	
	public void setActionBarView(ViewGroup actionbar) {
		if (actionbar == null) {
			return;
		}
		final int actionbarIndex = uxResideMainViewRoot.indexOfChild(uxResideMainViewRoot.findViewById(R.id.uxActionBar));
		if (actionbarIndex == -1) {
			return;
		}
		uxResideMainViewRoot.removeViewAt(actionbarIndex);
		uxResideMainViewRoot.addView(actionbar, actionbarIndex);
	}
	//TODO public method - END

	private void _setFragment(FragmentManager fm, int holderId, Fragment fragment) {
		if (fm == null && fragment == null) {
			throw new IllegalArgumentException("[INF] set fragment cannot be done, invalid argument!");
		}
		
		fm.beginTransaction().add(holderId, fragment).commit();
	}
	
//	@Override
//	public boolean dispatchTouchEvent(MotionEvent ev) {
//		return super.dispatchTouchEvent(ev);
//	}
	
	@Override
	protected void dispatchDraw(Canvas canvas) {
		// Draw the children
		super.dispatchDraw(canvas);
		
//		if (mState != MENU_CLOSED) {
//	        // The menu is not closed. That means we can potentially see the host
//	        // overlapping it. Let's add a tiny gradient to indicate the host is
//	        // sliding over the menu.
//	        canvas.save();
//	        canvas.translate(mHost.getLeft(), 0);
//	        mShadowDrawable.draw(canvas);
//	        canvas.restore();
//
//	        final int menuWidth = mMenu.getWidth();
//	        if (menuWidth != 0) {
//	            final float opennessRatio = (menuWidth - mHost.getLeft()) / (float) menuWidth;
//
//	            // We also draw an overlay over the menu indicating the menu is
//	            // in the process of being visible or invisible.
////	            onDrawMenuOverlay(canvas, opennessRatio);
//
//	            // Finally we draw an arrow indicating the feature we are
//	            // currently in
////	            onDrawMenuArrow(canvas, opennessRatio);
//	        }
//	    }
	}

	
//	private static final int MAXIMUM_MENU_ALPHA_OVERLAY = 170;
//
//	private void onDrawMenuOverlay(Canvas canvas, float opennessRatio) {
//	    final Paint menuOverlayPaint = mMenuOverlayPaint;
//	    final int alpha = (int) (MAXIMUM_MENU_ALPHA_OVERLAY * opennessRatio);
//	    if (alpha > 0) {
//	        menuOverlayPaint.setColor(Color.argb(alpha, 0, 0, 0));
//	        canvas.drawRect(0, 0, mHost.getLeft(), getHeight(), mMenuOverlayPaint);
//	    }
//	}
//	private static final float PARALLAX_SPEED_RATIO = 0.25f;
//
//	private void offsetMenu(int hostLeft) {
//	    final int menuWidth = mMenu.getWidth();
//	    if (menuWidth != 0) {
//	        final float opennessRatio = (menuWidth - hostLeft) / (float) menuWidth;
//	        mMenu.offsetLeftAndRight((int) (-opennessRatio * menuWidth * PARALLAX_SPEED_RATIO) - mMenu.getLeft());
//	    }
//	}
	
}
